﻿// ASP.NET Web API Sample Application
// by Lee Dumond -- leedumond@gmail.com

namespace ContactManagerCrud.Formatters
{
   using System;
   using System.Collections.Generic;
   using System.IO;
   using System.Net.Http.Formatting;
   using System.Net.Http.Headers;
   using Models;

   public class ContactCsvFormatter : BufferedMediaTypeFormatter
   {
      public ContactCsvFormatter()
      {
         SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
      }

      public override bool CanWriteType(Type type)
      {
         //serialize
         if (type == typeof(Contact))
         {
            return true;
         }

         Type enumerableType = typeof(IEnumerable<Contact>);

         return enumerableType.IsAssignableFrom(type);
      }

      public override bool CanReadType(Type type)
      {
         // deserialize
         return false;
      }

      public override void WriteToStream(Type type, object value, Stream stream, HttpContentHeaders contentHeaders)
      {
         using (var writer = new StreamWriter(stream))
         {
            var contacts = value as IEnumerable<Contact>;

            if (contacts != null)
            {
               foreach (var contact in contacts)
               {
                  WriteContactAsCsv(contact, writer);
               }
            }
            else
            {
               var contact = value as Contact;

               if (contact == null)
               {
                  throw new InvalidOperationException("Cannot serialize type");
               }

               WriteContactAsCsv(contact, writer);
            }
         }
         stream.Close();
      }

      // helper method to write a contact as a CSV line 
      private void WriteContactAsCsv(Contact contact, StreamWriter writer)
      {
         writer.WriteLine("{0},{1},{2},{3}", Escape(contact.Id), Escape(contact.Name), Escape(contact.Email), Escape(contact.Phone));
      }

      // escape special characters if any
      private string Escape(object o)
      {
         var specialChars = new[] { ',', '\n', '\r', '"' };

         if (o == null)
         {
            return "";
         }

         string field = o.ToString();

         return field.IndexOfAny(specialChars) != -1 ? String.Format("\"{0}\"", field.Replace("\"", "\"\"")) : field;
      }
   }
}